
public class DNodeQueue<E> implements IStack<E> {

	protected DNode<E> inSide; // reference to the head node
	protected DNode<E> outSide; // reference to the tail node
	protected int size; // number of elements in the stack
	

	public int size() {
		return size;
	}
	
	public boolean isEmpty() {
		return inSide == null;
	}


	public void push(E elem) {
		DNode<E> v = new DNode<E>(elem, null); // create and link-in a new node
		
		if(inSide != null){ // update the field previous on the old top if top exist
			inSide.setNext(v);
		} 
		
		if(outSide == null){
			outSide = v;
		}
		
		inSide = v;
		size++;
	}
	

	public E top() throws EmptyStackException {
		if (isEmpty())
			throw new EmptyStackException("Stack is empty.");
		
		return outSide.getElement();
	}
	
	
	public E pop() throws EmptyStackException {
		if (isEmpty())
			throw new EmptyStackException("Stack is empty.");
		
		E temp = outSide.getElement();
		outSide = outSide.getNext(); // link-out the former top node
		if(outSide == null){
			inSide = null;
		}
		size--;
		return temp;
	}
	
	public IStack<Object> copyToStack(IStack<Object> dest){
		
		DNode<E> node = outSide;
		while (node!=null) // while there is a new node, we continue
		{
			dest.push(node.getElement());
			node=node.getNext();
		}
		return dest;
	}

	@Override
	public String toString(){
		String output = "";

		DNode<E> node = outSide;
		while (node!=null) // while there is a new node, we continue
		{
			output += node.getElement().toString()+"\n"; // for each node we use the toString method of his element to describe the node
			node = node.getNext();
		}

		return output;
	}

}
